!function(window, fn) {
	if ('function' === typeof define && define.amd) {
		define(['utils'], function(_$) {
			return fn(_$);
		});
	} else {
		window.BaseCanvas = fn(utils);
	}
}(window, function(_$) {
	// 基础画布
	var BaseCanvas = function(canvas, ops) {
		if (canvas && canvas.getContext) {
			// 画布
			this.canvas = canvas;
			this.ctx = this.canvas.getContext("2d");
			this.setWidth(canvas.width);
			this.setHeight(canvas.height);
			// 状态
			this.states = {
				INIT: 'init',
				LOADED: 'loaded'
			};
			// 状态回调
			this.statescall = {
				// 初始化状态回调
				init: [function() {
					// 清空加载完成回调缓存
					this.statescall.loaded = [];
					this.state = this.states.INIT;
					this.ctx.clearRect(0, 0, this.width, this.height);
				}],
				// 图片加载完状态回调
				loaded: []
			};
			// 图片
			this.img = new Image();
		}
	};
	// 基础方法
	BaseCanvas.prototype = {
		// 初始化，首先检测浏览器是否支持canvas，不支持时不做任何操作
		init: function() {
			var c = this;
			c.updateState(c.states.INIT);
			c.img.onload = function() {
				if (!c.ctx) {
					return false;
				}
				c.drawImage();
			};
			return this;
		},
		// 字母转大写
		_toUpperCase: function(code) {
			return code && code.toUpperCase();
		},
		// 字母转小写
		_toLowerCase: function(code) {
			return code && code.toLowerCase();
		},
		// 增加状态
		addState: function(state) {
			state = this._toUpperCase(state);
			var name = this._toLowerCase(state);
			if (!this.states[state]) {
				this.states[state] = name;
			}
			if (!this.statescall[name]) {
				this.statescall[name] = [];
			}
			return this;
		},
		// 删除状态
		removeState: function(state) {
			state = this._toUpperCase(state);
			var name = this._toLowerCase(state);
			if (state !== 'INIT' && state !== 'LOADED') {
				delete this.states[state] && delete this.statescall[name];
			}
			return this;
		},
		// 更新状态，并执行状态函数
		updateState: function(state) {
			state = this._toUpperCase(state);
			var name = this._toLowerCase(state);
			if (this.states[state]) {
				this.state = this.states[state];
				if (this.statescall[name]) {
					var c = this;
					if (c.statescall[name] && c.statescall[name].length) {
						_$.each(c.statescall[name], function() {
							this.apply(c);
						});
					}
					if (name !== c.states.INIT) {
						c.statescall[name] = [];
					} else {
						c.clearStateExecution();
					}
				}
			}
			return this;
		},
		// 清空除初始化状态回调
		clearStateExecution: function() {
			var c = this;
			_$.each(c.statescall, function(key, value) {
				if (key.toString() !== c.states.init) {
					value = [];
				}
			});
		},
		// 获取状态
		getState: function() {
			return this.state;
		},
		// 设置宽（初始化时）
		setWidth: function(width) {
			if (!isNaN(width)) {
				this.width = width;
				this.setCanvasWidth(width);
			}
		},
		// 设置高（初始化时）
		setHeight: function(height) {
			if (!isNaN(height)) {
				this.height = height;
				this.setCanvasHeight(height);
			}
		},
		// 设置画布宽（绘图时）
		setCanvasWidth: function(width) {
			if (!isNaN(width)) {
				this.canvas.width = width;
				this.canvasWidth = width;
			}
		},
		// 设置画布高（绘图时）
		setCanvasHeight: function(height) {
			if (!isNaN(height)) {
				this.canvas.height = height;
				this.canvasHeight = height;
			}
		},
		// 执行状态函数
		executeState: function(state, fn) {
			state = this._toUpperCase(state);
			var name = this._toLowerCase(state);
			if (this.getState() === name) {
				fn.apply(this);
			} else if (this.states[state]) {
				this.statescall[name].push(fn);
			}
			return this;
		},
		// 加载图片
		loadImg: function(src) {
			if (this.getState() !== this.states.INIT) {
				this.init();
			}
			this.img.src = src;
			return this;
		},
		// 重新加载图片
		reloadImg: function() {
			if (this.img.src) {
				var src = this.img.src;
				this.img = new Image();
				this.init();
				this.loadImg(src);
			}
			return this;
		},
		// 获取图片最大尺寸
		getMaxImageSize: function() {
			var c = this, img = this.img, w = this.width, h = this.height, maxBorder = '', max = 0, proportion = 0;
			// 图片大小和画布尺寸不等时，采用同步缩放
			if (img.naturalWidth !== w || img.naturalHeight !== h) {
				// 比较长宽比，
				if (w / h > img.naturalWidth / img.naturalHeight) {
					max = img.naturalHeight;
					maxBorder = 'height';
				} else {
					max = img.naturalWidth;
					maxBorder = 'width';
				}
			}
			var width = w, height = h;
			// 计算等比缩放之后的宽、高
			if (max) {
				if (maxBorder === 'width') {
					proportion = max / w;
					height = Math.round(img.naturalHeight / proportion);
				} else {
					proportion = max / h;
					width = Math.round(img.naturalWidth / proportion);
				}
			}
			return {
				width: width,
				height: height
			};
		},
		// 绘图前置操作
		beforeDraw: function(maxSize) {
			throw new Error('Abstract function \'beforeDraw\' must be achievable.');
		},
		// 绘制图片
		drawImage: function() {
			var c = this, img = this.img, size = this.getMaxImageSize(), width = size.width, height = size.height;
			this.beforeDraw(size);
			// 画布大小
			var cW = this.canvasWidth || this.width, cH = this.canvasHeight || this.height;
			// 将图片等比缩放后居中绘制
			this.ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, Math.round((cW - width) / 2), Math.round((cH - height) / 2), width, height);
			// 如果图片大小和画布大小不等，绘制图片边界线
			if ((width !== cW || height !== cH) && this.drawImgBorder) {
				this._drawImageBorder(Math.round((cW - width) / 2), Math.round((cH - height) / 2));
			}
			this.afterDraw();
			this.updateState(this.states.LOADED);
			return this;
		},
		// 绘图后置操作
		afterDraw: function() {
			throw new Error('Abstract function \'afterDraw\' must be achievable.');
		},
		// 绘制图片的边界线
		_drawImageBorder: function(x, y) {
			if (x === 0 && y === 0) {
				return false;
			}
			this.ctx.beginPath();
			this.ctx.setLineDash([4, 2]);
			this.ctx.lineWidth = 1;
			if (x === 0) {
				y = Math.round(y) - 0.5;
				// 画两条横线
				this.ctx.moveTo(0, y);
				this.ctx.lineTo(this.width, y);
				this.ctx.moveTo(0, this.height - y);
				this.ctx.lineTo(this.width, this.height - y);
			} else {
				x = Math.round(x) - 0.5;
				// 画纵边界线
				this.ctx.moveTo(x, 0);
				this.ctx.lineTo(x, this.height);
				this.ctx.moveTo(this.width - x - 1, 0);
				this.ctx.lineTo(this.width - x - 1, this.height);
			}
			// 绘制的颜色
			this.ctx.strokeStyle = 'rgba(255, 0, 0, 0.8)';
			// 绘制边框
			this.ctx.stroke();
		},
		// 绑定到指定的图片文件选择框
		bindFileInput: function(fileInput) {
			var c = this;
			// 文件改变时触发画布重新加载图片
			fileInput.onchange = function() {
				// 初始化状态
				c.updateState(c.states.INIT);
				var file = fileInput.files && fileInput.files[0];
				// 文件类型或文件名长度不符
				if (!file || !file.type.match(/image.*/)) {
					return false;
				}
				var reader = new FileReader();
				reader.onloadend = (function() {
					return function(e) {
						c.loadImg(e.target.result);
					};
				})();
				reader.readAsDataURL(file);
			};
			fileInput.onchange.apply(fileInput);
			return this;
		}
	};
	return BaseCanvas;
});